home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / tvalt.exe / READ.ME < prev    next >
Text File  |  1992-10-05  |  9KB  |  195 lines

  1.     Many times I've heard users requesting a method to use Turbo Vision using
  2. BIOS screen writes instead of the default direct-video access method; an even
  3. LARGER group of users want to use TV in graphics mode. This file contains
  4. the information necessary to implement this.
  5.     Graphics users:
  6.     Deep down in its guts, TV is optimized for character-based drawing to the
  7. screen; this is obvious from the write methods available in the class TView:
  8. they all convert their arguments into a buffer of unsigned chars whose format
  9. is in [attribute][character] pairs - this is for quick direct-transfer to
  10. video memory. No matter WHAT method is used to convert this information to
  11. graphics-calls type information, the process is not quick. For example: when
  12. a 'blank' view paints itself, it fills a buffer with the space character and
  13. the desired attribute, then it calls one of the write methods to draw this
  14. 'line' of data for every line in the view. In graphics mode, all you want to
  15. do is bar(...) to fill in the window. The method I present here tries to
  16. optimize this char-based => graphics-based process, but the speed difference
  17. is still quite noticable.
  18.     This file, however, is NOT exclusively devoted to graphics-based TV: its
  19. devoted to using an alternate write method for screen drawing. Whether that
  20. alternate method is BIOS calls, graphics painting, etc is not relevant; I
  21. give an example of both in the code.
  22.     To enable an alternative write method requires modification of the TV
  23. source code, and source file TVWRITE.ASM in particular. In this read me file
  24. I will list and explain the assembly changes needed for this file; for those
  25. users who do not have the TV source code I am including USEWRITE.OBJ and
  26. NOWRITE.OBJ - the assembled TVWRITE.ASM (I cannot include the modified
  27. TVWRITE.ASM since that is copyrighted material of Borland International's).
  28. Whether you modify the source itself, or use xxxWRITE.OBJ, I *STRONGLY* urge
  29. you to NOT place this code change in TV.LIB. Instead, just include the new
  30. TVWRITE.ASM (or xxxWRITE.OBJ) in your project that requires the alternate
  31. write method. The difference between NO/USEWRITE.OBJ is in its default
  32. behaviour and is described below.
  33.  
  34.     TVWRITE.ASM has a procedure declared which, in the header files, is:
  35.         static void writeView( write_args );
  36. This is the actual procedure that writes to the screen in Turbo Vision: all
  37. other write methods put their data into a write_args format and call
  38. TView::writeView(). So it is here that the fundamental changes to TV must be
  39. made.
  40.     The first thing we need is some type of global flag that can enable or
  41. disable this option. Here's what's needed for that: at the top of TVWRITE.ASM
  42. you will see a number of PUBLIC ... statements. After the last PUBLIC
  43. statement and before the first EXTRN statement, add the public declaration
  44. for the variable so that it looks like:
  45.         ...
  46.         PUBLIC  @TView@writeStr$qssnxzcuc
  47. ; --------------------- NEW -------------------------
  48.         PUBLIC    _useAltWriteMethod
  49. ; ---------------------------------------------------
  50.         EXTRN   @THWMouse@show$qv : PROC
  51.         ...
  52. This declares our variable public so that other modules can access it. As
  53. long as you're in this area of the code, there's something else we need to
  54. add. When this flag is non-zero (and the write is being performed to the
  55. screen versus a TGroup buffer), we want to call a function that will perform
  56. the actual screen writing. To call this function we have to give the function
  57. a name, and let TVWRITE.ASM know that its a function that is external to this
  58. module. To do that, add the statement to the end of the list of EXTRN ...
  59. statements, so that it looks like this:
  60.         ...
  61.         EXTRN   @TScreen@checkSnow : BYTE
  62. ; --------------------- NEW -------------------------
  63.         EXTRN    @altWriteMethod$qsssnuss : PROC
  64. ; ---------------------------------------------------
  65.  
  66. STRUC   Fptr
  67.     ...
  68. This lets the assembler know that we are going to call the function whose
  69. declaraction is:
  70.     void altWriteMethod( short,short, short, ushort *, short );
  71. and to take this name into account when assembling. Now we have a flag name
  72. that is globally accessable, and some external function we can call to
  73. perform a screen write. Next we need to actually declare the flag so as to
  74. allocate memory for it. A few lines below these EXTRN statements you'll see
  75. the directive DATASEG - this directive tells the assembler that the
  76. following lines of data are to be allocated into the default data segment
  77. DGROUP: it is here that we want to allocate our flag. Insert it so that it
  78. looks like:
  79. ...
  80. DATASEG
  81.  
  82. wArgs   WriteArgs       ?
  83. ; --------------------- NEW -------------------------
  84. _useAltWriteMethod    DW    1
  85. ; ---------------------------------------------------
  86.  
  87. IFDEF 0; PROTECT
  88. ...
  89. Note that the '1' initializes _useAltWriteMethod to 1; this is the TV
  90. equivalent of:
  91.     Boolean useAltWriteMethod = True;
  92. The definition of our flag (useAltWriteMethod) is that a value of 0 indicates
  93. that the alternate write method should NOT be use; a non-zero value says to
  94. use the alternative method. By using the above declaration, we are telling
  95. the program to, by default, use the alternative method. If you desire that
  96. the default (startup) action to be to NOT use the alternative method, change
  97. the 1 above to a 0. The included USEWRITE.OBJ has a default of True for
  98. useAltWriteMethod; the included NOWRITE.OBJ has a default of False.
  99.     Now we have to change TView::writeView() to use altWriteMethod() to draw
  100. instead of the default method (when useAltWriteMethod <> 0 and writeView() is
  101. drawing to the screen). TView::writeView() does a lot more than just write a
  102. line of char-attr pairs to the screen - it searches through the view
  103. hierarchy and takes into account overlapping windows, shadows, etc. But there
  104. is one point in writeView() when everything has been taken into account, and
  105. the code is ready to write the data to the screen. This is in the vicinity
  106. of label @@50, and this is where we'll make our change. When the program
  107. gets to label @@50, the following conditions hold:
  108.     AX = the y coordinate (0-based) on the screen of the line to write to.
  109.     BX = the x coordinate (0-based) on the screen where the write starts.
  110.     CX = the x coordinate (0-based) on the screen where the write ends.
  111.     DX = 0 if the buffer's attributes should be used, non-zero if the
  112.         shadowAttr should be used.
  113.     SI = the segment of the destination address. If SI =
  114.         FP_SEG(TScreen::screenBuffer) then this write is aimed at the screen.
  115.     wArgs.Buffer = the buffer start address.
  116.     wArgs.Offset = the offset into the buffer to use.
  117.     the actual buffer start for BX is at wArgs.Buffer+(BX-wArgs.Offset)
  118.  
  119.     The format that we want altWriteMethod to be in is:
  120.         void altWriteMethod( short x, short y, short wid, ushort *buf,
  121.             short sflag );
  122. where:
  123.         (x,y) is the starting column/row on the screen (0-based),
  124.         wid is the number of entries in the buffer to write,
  125.         buf is the buffer,
  126.         sflag is the shadow flag (0 = use buffer attributes, <>0 = use
  127.             shadowAttr declared in TVIEW.CPP.
  128.  
  129. Here's how to implement the call in TVWRITE.ASM:
  130. ...
  131. @@50:
  132.         PUSH    ES
  133.         PUSH    DS
  134.         PUSH    DI
  135.         PUSH    CX
  136.         PUSH    AX
  137.  
  138. ; --------------------- NEW -------------------------
  139.     ; call only if its a screen write (ignore TGroup::buffer writes).
  140.         CMP        SI, [WORD PTR @Tscreen@screenBuffer+2]
  141.         JNE        @@55
  142.     ; call only if useAltWriteMethod <> 0.
  143.         TEST    [_useAltWriteMethod],0FFFFh
  144.         JE        @@55
  145.  
  146.         PUSH    BX
  147.         PUSH    DX
  148.         PUSH    SI
  149.  
  150.     ; push sflag argument.
  151.         PUSH    DX
  152.     ; push buf's segment.
  153.         PUSH    [wArgs.Buffer.segm]
  154.     ; compute and push buf's offset.
  155.         MOV        SI,BX
  156.         SUB        SI,[wArgs.Offset]
  157.         SHL        SI,1
  158.         ADD        SI,[wArgs.Buffer.offs]
  159.         PUSH    SI
  160.     ; compute and push wid.
  161.         SUB        CX,BX
  162.         PUSH    CX
  163.     ; push y.
  164.         PUSH    AX
  165.     ; push x.
  166.         PUSH    BX
  167.     ; call void altWriteMethod(short,short,short,ushort *,short);
  168.         CALL    @altWriteMethod$qsssnuss
  169.         ADD        SP,12
  170.  
  171.         POP        SI
  172.         POP        DX
  173.         POP        BX
  174.     ; restore conditions and jump around the screen-writing routines.
  175.         MOV        ES,SI
  176.         JMP        @@70
  177. @@55:
  178. ; ---------------------------------------------------
  179.  
  180.